package festival.player;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;

import javax.swing.JPanel;

public class PlayerView extends JPanel implements ComponentListener {
    public static Color[] sTileColors = {
        new Color(0xFF825e45),
        new Color(0xFF50c248),
        new Color(0xFF156fdf),
        new Color(0xFF983232)
    };
    
    public static Color[] sDevColors = {
        Color.ORANGE,
        Color.RED,
        Color.WHITE,
        Color.BLACK
    };
    
    private static Color TRANSPARENT =  new Color(0, 0, 0, 0);
    
    private double mPadding;
    private Player mPlayer;
    private boolean mInit;
    
    private int mIcFontSize;
    
    private int mPlayerFontSize;
    private int mMiscFontSize;
    
    private int mDrawableWidth;
    private int mDrawableHeight;
    
    private double mHexWidth;
    private double mHexHeight;
    private double mHexSide;
    private double mHexRadius;
    private double mHexDx;
    private double mHexDy;
    
    private boolean mIsSelected;
    
    public PlayerView(Player player) {
        super();
        mPlayer = player;
        
        addComponentListener(this);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(mInit) {
            int yOffset = (int) mPadding;
            int xOffset = (int) mPadding;
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setColor(Color.BLACK);
            Rectangle rect = new Rectangle((int) mPadding, (int) mPadding, 100, 100);
            Font font = new Font(Font.SANS_SERIF, Font.BOLD, mPlayerFontSize);
            g2.setFont(font);
            
            if(mIsSelected) {
                g2.setColor(new Color(0, 255, 0, 50));
                g2.fillRect(1, 1, getWidth() - 2, getHeight() - 2);
            }
            g2.setColor(Color.BLACK);
            
            int sixth = mDrawableWidth / 6;

            FontMetrics fontMetrics = g2.getFontMetrics();
            int playerTextHeight = fontMetrics.getHeight();
            yOffset = playerTextHeight;
            g2.drawString("Player " + (mPlayer.getId() + 1), xOffset, yOffset);
//            g2.draw(rect);
            yOffset += fontMetrics.getDescent();
//            xOffset += mHexWidth / 2;
//            yOffset += 10;
            xOffset = sixth;
            font = new Font(Font.SANS_SERIF, Font.BOLD, mMiscFontSize);
            g2.setFont(font);
            
            int row1 = (int) (yOffset + mHexRadius * 2.1);
            int row2 = (int) (row1 + mHexHeight * 1.6);
            int row3 = (int) (row2 + mHexHeight * 1.6);
            
//            yOffset += mHexHeight * 2;
//            double dx = mHexWidth * 1.5;
//            double y = yOffset - mHexHeight / 2;
            double y = yOffset + mHexRadius * 2;
            drawCircleAtPixel(new double[] { xOffset, row1 }, sDevColors[(mPlayer.getId())], mHexRadius * 2, g2);
            
            yOffset += mHexHeight * 1.8;
            drawStringCenteredBoth(g2, mPlayer.getDeveloperCount() + "", xOffset, row2);
            
            yOffset -= mHexHeight * 1.8;
            xOffset += sixth;
            y = yOffset + mHexRadius;
            double x = xOffset;
            double y1 = row1 - (mHexHeight * (3.0 / 8.0));
            double y2 = row1 + (mHexHeight * (3.0 / 8.0));
            drawHexagonAtPixel(g2, new double[] { x, y1 }, sTileColors[1], mHexRadius);
            drawHexagonAtPixel(g2, new double[] { mHexDx + x, y2 }, sTileColors[0], mHexRadius);
            
            yOffset += mHexHeight * 1.8;
            xOffset += (mHexWidth * 0.25);
            
            drawStringCenteredBoth(g2, mPlayer.getTwoSpaceTileCount() + "", xOffset, row2);
            
            yOffset -= mHexHeight * 1.8;
            xOffset += sixth;
            y = yOffset + mHexRadius * 2;
            drawHexagonAtPixel(g2, new double[] { xOffset, row1 }, sTileColors[1], mHexRadius * 2);
            
            
            yOffset += mHexHeight * 1.8;
            
            drawStringCenteredBoth(g2, mPlayer.getRiceTileCount() + "", xOffset, row2);
            
            yOffset -= mHexHeight * 1.8;
            xOffset += sixth;
            y = yOffset + mHexRadius * 2;
            drawHexagonAtPixel(g2, new double[] { xOffset, row1 }, sTileColors[0], mHexRadius * 2);
            
            
            yOffset += mHexHeight * 1.8;
            
            drawStringCenteredBoth(g2, mPlayer.getVillageTileCount() + "", xOffset, row2);
            
            yOffset -= mHexHeight * 1.8;
            yOffset += mHexHeight * 0.5;
            xOffset += sixth;
//            y = yOffset + mHexRadius * 2;
            drawStringCenteredBoth(g2, "AT", xOffset, row1);
            
            
            yOffset -= mHexHeight * 0.5;
            yOffset += mHexHeight * 1.8;
            
            drawStringCenteredBoth(g2, mPlayer.getActionTokenCount() + "", xOffset, row2);
            
            xOffset += sixth;
//          y = yOffset + mHexRadius * 2;
            drawStringCenteredBoth(g2, "PC", xOffset, row1);


            yOffset -= mHexHeight * 0.5;
            yOffset += mHexHeight * 1.8;

            drawStringCenteredBoth(g2, mPlayer.getPalaceCardCount() + "", xOffset, row2);
            
            drawStringCenteredBoth(g2, "Fame: " + mPlayer.getVictoryPoints(), mDrawableWidth / 2, row3);
//            for(int i = 0; i < 5; i++) {
//                if((i+1) <= mPlayer.getTwoSpaceTileCount()) {
//                    drawHexagonAtPixel(new double[] { xOffset + i * dx, y }, sTileColors[1], mHexRadius);
//                    drawHexagonAtPixel(new double[] { mHexDx + xOffset + i * dx, y + mHexDy }, sTileColors[0], mHexRadius);
//                } else {
//                    drawHexagonAtPixel(new double[] { xOffset + i * dx, y }, TRANSPARENT, mHexRadius);
//                    drawHexagonAtPixel(new double[] { mHexDx + xOffset + i * dx, y + mHexDy }, TRANSPARENT, mHexRadius);
//                }
//            }
//            yOffset += mHexHeight * 2;
//            y = yOffset + mHexRadius;
//            for(int i = 0; i < mPlayer.getRiceTileCount(); i++) {
////                xOffset += mHexWidth;
//                drawHexagonAtPixel(new double[] { xOffset + i * dx, y }, sTileColors[1], mHexRadius);
//            }
//            
//            yOffset += mHexHeight + (mHexRadius / 2);
//            y = yOffset + mHexRadius;
//            for(int i = 0; i < mPlayer.getVillageTileCount(); i++) {
////              xOffset += mHexWidth;
//              drawHexagonAtPixel(new double[] { xOffset + i * dx, y }, sTileColors[0], mHexRadius);
//            }
//            
//            font = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
//            g2.setFont(font);
//            int thirdOffset = mDrawableWidth / 2;
//            
//            yOffset += g2.getFontMetrics().getHeight() * 2;
//            g2.drawString("Developers: " + mPlayer.getDeveloperCount(), xOffset, yOffset);
//            xOffset += thirdOffset;
//            g2.drawString("Action tokens: " + mPlayer.getActionTokenCount(), xOffset, yOffset);
//            
//            xOffset = (int) mPadding;
//            yOffset += g2.getFontMetrics().getHeight();
//            
////            g2.drawString("Two-space tiles: " + mPlayer.getTwoSpaceTileCount(), xOffset, yOffset);
//            
//            yOffset += mHexHeight * 2 - mHexHeight / 2;
//            xOffset += thirdOffset;
//            g2.drawString("Rice tiles: " + mPlayer.getRiceTileCount(), xOffset, yOffset);
//
//            xOffset = (int) mPadding;
//            yOffset += g2.getFontMetrics().getHeight();
//            
//            g2.drawString("Village tiles: " + mPlayer.getVillageTileCount(), xOffset, yOffset);
//            xOffset += thirdOffset;
//            g2.drawString("Palace cards: " + mPlayer.getPalaceCardCount(), xOffset, yOffset);
        }
    }
    
    private void drawStringCenteredVertical(Graphics2D g2, String s, int XPos, int YPos) {  
        int stringLen = (int) g2.getFontMetrics().getStringBounds(s, g2).getWidth();  
        int start = XPos - stringLen/2;  
        drawStringOffset(g2, s, start, YPos);  
    }
    
    private void drawStringCenteredBoth(Graphics2D g2, String s, int x, int y) {  
        // Find the size of string s in the font of the Graphics context "page"
        FontMetrics fm   = g2.getFontMetrics(g2.getFont());
        java.awt.geom.Rectangle2D rect = fm.getStringBounds(s, g2);
        int textHeight = (int)(rect.getHeight());
        int textWidth  = (int)(rect.getWidth());

        // Center text horizontally and vertically within provided rectangular bounds
        int textX = x - (textWidth)/2;
        int textY = y - (textHeight)/2 + fm.getAscent();
        g2.drawString(s, textX, textY);
    }
    
    private void drawStringOffset(Graphics2D g2, String s, int xpos, int ypos) {
        int stringHeight = (int) g2.getFontMetrics().getStringBounds(s, g2).getHeight();
        int y = ypos + stringHeight;
        g2.drawString(s, xpos, y);
    }
    
    private void drawHexagonAtPixel(Graphics2D g2, double[] pixels, Color color, double radius) {
        double centerX = pixels[0];
        double centerY = pixels[1];
        
        Path2D.Double hex = new Path2D.Double();
        for(int q = 0; q < 7; q++) {
            double radians = ((q * 60) + 30) * Math.PI / 180;
            if(q == 0) {
                hex.moveTo(centerX + radius * Math.cos(radians), centerY + radius * Math.sin(radians));
            } else {
                hex.lineTo(centerX + radius * Math.cos(radians), centerY + radius * Math.sin(radians));
            }
        }
        
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setStroke(new BasicStroke(2));
        
        g2.setColor(color);
        g2.fill(hex);
        
        g2.setColor(Color.BLACK);
        g2.draw(hex);
    }
    
    // TODO
    private void drawCircleAtPixel(double[] pixels, Color color, double radius, Graphics2D g2) {
        double centerX = pixels[0];
        double centerY = pixels[1];
        
        Ellipse2D circle = new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2);
        
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setStroke(new BasicStroke(2));
        
        g2.setColor(color);
        g2.fill(circle);
        
        g2.setColor(Color.BLACK);
        g2.draw(circle);
    }
//  12 developers in his color
//  3 extra action tokens
//  5 2 space land tiles
//  3 1 space rice field land tiles
//  2 1 space village or city land tiles 1 action summary card
//  3 face down palace cards
    
    public void componentHidden(ComponentEvent arg0) {
    }

    public void componentMoved(ComponentEvent arg0) {
    }

    public void componentResized(ComponentEvent arg0) {
        initSize();
    }

    public void componentShown(ComponentEvent arg0) {
        initSize();
    }
    
    private void initSize() {
        double width = getWidth();
        double height = getHeight();
        
        mPadding = width > height ? height * 0.1 : width * 0.1;
        
        mDrawableWidth = (int) (width - (2 * mPadding));
        mDrawableHeight = (int) (height - (2 * mPadding));
        
        double hexScale = 0.05;
        double fontScale = 1.0;
        double titleScale = 1.0 / 5.0;
        double icFontScale = 0.9;
        if(width > height) {
            mHexWidth = mDrawableWidth * hexScale;
            mHexSide = mHexWidth / (2 * Math.cos(Math.PI / 6));
            mHexHeight = 2 * mHexSide;
            mPlayerFontSize = (int) (mDrawableHeight * titleScale);
            mMiscFontSize = (int) (mDrawableHeight * fontScale);
            mIcFontSize = (int) (mDrawableHeight * icFontScale);
        } else {
            mHexWidth = mDrawableWidth * hexScale;
            mHexSide = mHexWidth / (2 * Math.cos(Math.PI / 6));
            mHexHeight = 2 * mHexSide;
            mPlayerFontSize = (int) (mDrawableWidth * titleScale);
            mMiscFontSize = (int) (mDrawableWidth * fontScale);
            mIcFontSize = (int) (mDrawableWidth * icFontScale);
        }
        
        double colWidth = (mDrawableWidth / 6.0) / 2.0;
        mHexWidth = colWidth * 0.85;
        mHexSide = mHexWidth / (2 * Math.cos(Math.PI / 6));
        mHexHeight = 2 * mHexSide;
        mMiscFontSize = (int) (colWidth * fontScale);
        mIcFontSize = (int) (colWidth * icFontScale);

//        mHexRadius = mHexSide / (2 * Math.sin(Math.PI / 6));
        mHexRadius = mHexSide;

        mHexDy = (3 * mHexSide) / 2;
        mHexDx = mHexWidth / 2;
        
        mInit = true;
        repaint();
    }
    
    public void setSelected(boolean selected) {
        mIsSelected = selected;
    }
}
